
/**********************************************************************************\
** 文件名称: list.c
** 创建人员: YCG
** 创建日期: 2018-12-14
** 文档描述: 双向列表
** 1.
** 版本代号: V0.1
** 版本说明: 初始版本
\********************************************************************************/
#include	"list.h"
#include	"uart.h"

/*******************************************************************************
** 函数名称: ListInit
** 功能描述: 初始化列表
** 参数说明: pxList: [输入]  需要初始化的列表
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-14
********************************************************************************/
void ListInit(List_t * const pxList) {

    pxList->Index = &(pxList->EndItem);           //此时的地址指向本身

    pxList->EndItem.Head  = pxList;               //头部是本身
    pxList->EndItem.Next  = &(pxList->EndItem);   //表头的列表项的下一个指向表头的列表项本身
    pxList->EndItem.Pre   = &(pxList->EndItem);   //表头的列表项的上一个一个指向表头的列表项本身
    pxList->EndItem.Value = LIST_VALUE_MAX;       //表头的列表项的值初始化为最大值

    pxList->ListNum = 0U;                         //除了表头以外，列表项数量初始化为0
}

/*******************************************************************************
** 函数名称: ListItemInit
** 功能描述: 初始化列表项
** 参数说明: pxItem: [输入] 需要初始化的列表项
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-14
********************************************************************************/
void ListItemInit(ListItem_t * const pxItem) {
    pxItem->Head = NULL;
}

/*******************************************************************************
** 函数名称: ListInsertEnd
** 功能描述: 插入列表项到列表当前位置的前面
** 参数说明: pxList: [输入]   操作的列表
**			 pxNewItem: [输入]    需要插入的列表项
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-14
********************************************************************************/
void ListInsertEnd(List_t * const pxList, ListItem_t * const pxNewItem) {
    ListItem_t * const pxItem = pxList->Index;     //获取当前的位置

    if(pxNewItem->Head == NULL) { //避免重复添加
        pxNewItem->Next = pxItem;        //新列表项的下一个是旧的列表项
        pxNewItem->Pre  = pxItem->Pre;   //新列表项的上一个是旧的列表项上一个

        pxItem->Pre->Next = pxNewItem;  //旧列表项的上一个的下一个是新列表项
        pxItem->Pre = pxNewItem;        //旧列表项的上一个是新列表项

        pxNewItem->Head = pxList;          //添加到列表中

        pxList->ListNum += 1 ;          //列表中的列表项计数加一
    }
}

/*******************************************************************************
** 函数名称: ListInsert
** 功能描述: 按照列表项的值从大到小插入
** 参数说明: pxList: [输入]    操作的列表
**			 pxNewItem: [输入]     需要插入的列表项
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-14
********************************************************************************/
void ListInsert(List_t * const pxList, ListItem_t * const pxNewItem) {

    ListItem_t *  pxItem ;                       //操作的列表项对象
    const uint32_t pxValue = pxNewItem->Value;   //需要插入的列表项的值
    if(pxNewItem->Head == NULL) { //避免重复添加
        if(pxValue == LIST_VALUE_MAX) {              //避免进入死循环
            pxItem = pxList->EndItem.Pre;            //是最大值的话插入到末尾
        } else {
            //从第一个开始遍历列表，直到找到插入列表项的值大于的位置
            for(pxItem = (pxList->EndItem.Next); pxItem->Value <= pxValue; pxItem = pxItem->Next) {}
        }
        pxNewItem->Next = pxItem;       //新列表项的下一个是旧的列表项
        pxNewItem->Pre = pxItem->Pre;   //新列表项的上一个是旧的列表项上一个
        pxItem->Pre->Next = pxNewItem;  //旧列表项的上一个的下一个是新列表项
        pxItem->Pre = pxNewItem;        //旧列表项的上一个是新列表项

        pxNewItem->Head = pxList;          //添加到列表中

        pxList->ListNum += 1 ;          //列表中的列表项计数加一
    }
}

/*******************************************************************************
** 函数名称: ListIRemove
** 功能描述: 移除对应的列表项
** 参数说明: pxRemoveItem: [输入] 需要移除的列表项
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-14
********************************************************************************/
void ListRemove(ListItem_t * const pxRemoveItem) {
    List_t * const pxList = pxRemoveItem->Head;
    if(pxList != NULL) {       //避免是空的列表

        pxRemoveItem->Next->Pre = pxRemoveItem->Pre;        //移除列表项的下一个的前一个指向移除列表项的前一个
        pxRemoveItem->Pre->Next = pxRemoveItem->Next;       //移除列表项的前一个的下一个指向移除列表项的下一个

        if(pxList->Index == pxRemoveItem) {      //如果当前列表的索引指向移除列表项
            pxList->Index = pxRemoveItem->Pre;   //将索引指向移除列表项的前一个
        }
        pxRemoveItem->Head = NULL;      //移除列表项的表头清空

        pxList->ListNum -= 1 ;          //列表中的列表项计数减一
    }
}

/*******************************************************************************
** 函数名称: PrintList
** 功能描述: 打印列表
** 参数说明: pxList: [输入] 需要打印的列表
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-14
********************************************************************************/
void ListPrint(List_t * const pxList) {

    Uprintf("\r\n列表地址:   0x%-10x 列表数量:   %-5d\r\n", pxList, pxList->ListNum);

    for(ListItem_t* pxListItem = LIST_GET_HEAD(pxList); LISTITEM_IS_NOT_END(pxListItem); LISTITEM_TO_NEXT(pxListItem)) {
        Uprintf("列表项地址: 0x%-10x 列表项值: %-5d\r\n", pxListItem, pxListItem->Value);
    }

}

/********************************End of File************************************/
